import path = require('path');
const fs = require('fs');
const express = require('express');
const config = require('../config');
// const passport = require('passport');
// const session = require('express-session');
// const RedisStore = require('connect-redis')(session);
// import {graphiqlExpress, graphqlExpress} from 'graphql-server-express';
// import cacheClient from './lib/core/cacheClient';
// import pubsubClient from './lib/core/pubsubClient';
// import schemaUser from './graphql/user/schema';
// import schemaOperator from './graphql/operator/schema';
// import schemaMobile from './graphql/mobile/schema';

// import jobs from './jobs';

export class Server {
  private _app;
  private _rootRouter = express.Router();

  public start() {
    const app = express();
    app.disable('x-powered-by');
    this._app = app;
    this.onMountingMiddlewares(app);
    const server = require('http').createServer(app);
    server.listen(config.serverPort, () => {
      console.log(`Server started at port ${config.serverPort}.`);
    });
    // const io = require('socket.io')(server);
    // pubsubClient.client.on('subscribe', (channel, count) => {
    //   console.log('日志订阅成功');
    // });
    // pubsubClient.client.on('message', (channel, message) => {
    //   io.emit(channel, message);
    // });
    // pubsubClient.client.subscribe('logstash');
  }

  private mountControllers(controllerPath, baseUrlPath = '/') {
    const fullPath = path.resolve(__dirname) + controllerPath;
    this.loadControllersRecursive(fullPath, baseUrlPath);
    this._app.use(baseUrlPath, this._rootRouter);
  }

  private loadControllersRecursive(dir, url) {
    try {
      if (!fs.existsSync(dir)) {
        return;
      }
      fs.readdirSync(dir).forEach(file => {
        const path = dir + '/' + file;
        const stats = fs.lstatSync(path);
        if (stats.isDirectory()) {
          let baseUrl = url;
          if (baseUrl === '/') {
            baseUrl = baseUrl + file;
          } else {
            baseUrl = baseUrl + '/' + file;
          }
          this.loadControllersRecursive(path, baseUrl);
        } else if (/\.(js)$/.test(path)) {
          const router = express.Router();
          require(path).default(this._app, router);
          this._rootRouter.use(url, router);
        }
      });
    } catch (err) {
      console.log(err.stack);
    }
  }

  onMountingMiddlewares(app) {
    const morgan = require('morgan');
    app.use(morgan('dev'));

    const staticPath = process.cwd() + '/client/static';
    app.use(express.static(staticPath));

    const cookieParser = require('cookie-parser');
    const bodyParser = require('body-parser');
    const compress = require('compression');
    const methodOverride = require('method-override');

    app.use(cookieParser())
      .use(compress({}))
      .use(methodOverride())
      .use(bodyParser.json())
      .use(bodyParser.urlencoded({
        extended: true
      }));

    // app.use((req, res, next) => {
    //   if (req && req.headers.authorization && req.headers.authorization.indexOf('Bearer') === 0) {
    //     app.use(passport.initialize());
    //     passport.authenticate('bearer', {session: false})(req, res, next);
    //   } else {
    //     const sessionMiddleware = express.Router();
    //     sessionMiddleware.use(session({
    //       cookie: {maxAge: 60000 * 60 * 24},
    //       store: new RedisStore({host: config.redis.host, port: config.redis.port, pass: config.redis.pass}),
    //       secret: 'bfftrip2017',
    //       resave: true,
    //       rolling: true,
    //       saveUninitialized: true
    //     }));
    //     sessionMiddleware.use(passport.initialize());
    //     sessionMiddleware.use(passport.session());
    //     sessionMiddleware(req, res, next);
    //   }
    // });

    this.mountControllers('/controllers');

    // app.post('/gql', bodyParser.json(), graphqlExpress((req) => ({schema: schemaUser, context: req})));
    // app.post('/gql/user', bodyParser.json(), graphqlExpress((req) => ({ schema: schemaUser, context: req })));
    // app.post('/gql/op', bodyParser.json(), graphqlExpress((req) => ({ schema: schemaOperator, context: req })));
    // app.post('/gql/mobile', bodyParser.json(), graphqlExpress((req) => ({ schema: schemaMobile, context: req })));
    // app.get('/gql/user', graphiqlExpress({endpointURL: '/gql/user'}));
    // app.get('/gql/op', graphiqlExpress({endpointURL: '/gql/op'}));
    // app.get('/gql/mobile', graphiqlExpress({endpointURL: '/gql/mobile'}));
    return null;
  }

  public onServerInitError(err) {
    console.error(err);
  }

  static Initialize = async () => {
    const server = new Server();
    try {
      console.log(config.env);
      console.log(config.configEnv);
      // cacheClient.initialize(config.redis);
      // pubsubClient.initialize(config.redis);
      server.start();
      // jobs.startAll();
    } catch (err) {
      server.onServerInitError(err);
    }
  }
}
